package com.app.framework.utils;

import com.app.exception.BusinessException;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.lionsoul.ip2region.xdb.Searcher;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.io.InputStream;
import java.util.HashMap;

/**
 * Ip工具类
 */
@Slf4j
@Component
public class IpUtils {

    private static Searcher searcher;

    /**
     * 获取真实IP地址
     */
    public static String getIp() {
        //获取请求相关信息
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    /**
     * 根据IP从IP库中获取地理位置
     *
     * @param ip IP
     */
    public static HashMap<String, Object> getCityInfo(String ip) {
        HashMap<String, Object> cityInfo = new HashMap<>();
        try {
            String searchIpInfo = searcher.search(ip);
            String[] splitIpInfo = searchIpInfo.split("\\|");
            cityInfo.put("ip", ip);
            cityInfo.put("searchInfo", searchIpInfo);
            cityInfo.put("country", splitIpInfo[0]);
            cityInfo.put("region", splitIpInfo[1]);
            cityInfo.put("province", splitIpInfo[2]);
            cityInfo.put("city", splitIpInfo[3]);
            cityInfo.put("isp", splitIpInfo[3]);
            return cityInfo;
        } catch (Exception e) {
            throw new BusinessException("查询失败");
        }
    }

    /**
     * 服务启动时加载IP库到内存中
     */
    @PostConstruct
    private static void initIp2regionResource() {
        try {
            InputStream inputStream = new ClassPathResource("/ipdb/ip.xdb").getInputStream();
            byte[] dbBinStr = FileCopyUtils.copyToByteArray(inputStream);
            //创建一个完全基于内存的查询对象
            searcher = Searcher.newWithBuffer(dbBinStr);
            log.info("IP库初始化完成");
        } catch (Exception e) {
            log.error("IP库初始化失败");
        }
    }

}
